import { Injectable, Inject, HttpException, HttpStatus } from '@nestjs/common';
import { PrismaService } from '@/prisma/prisma.service';
import { PaginationService } from '@/hooks/usePagination';
import { MinioClientService } from '@/minio/MinioClient.service';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';

@Injectable()
export class ScenicControlService {
  @Inject(PrismaService)
  private readonly prisma: PrismaService;

  @Inject(PaginationService)
  private readonly paginationService: PaginationService;

  @Inject(MinioClientService)
  private readonly MinioClientService: MinioClientService;

  @Inject(ConfigService)
  private readonly configService: ConfigService;

  async getAdressCode(address: string) {
    const url = this.configService.get('gaode.api');
    const key = this.configService.get('gaode.key');

    const response = await axios.get(url, {
      params: { key, address },
    });
    return response.data;
  }

  async getFillInfo(data) {
    const { geocodes: info } = await this.getAdressCode(data.addr);

    if (!info?.length) {
      throw new HttpException('请填写正确的地址', HttpStatus.BAD_REQUEST);
    }
    const region =
      info[0].province + '-' + info[0].city + '-' + info[0].district;
    const [lng, lat] = info[0].location.split(',');
    return { ...data, region, lng, lat };
  }

  async getScenicList(pageNum, pageSize, spot, region, type, sort) {
    const query = {
      where: {
        type,
        region: {
          contains: region,
        },
        spot: {
          contains: spot,
        },
      },
      include: {
        scenic_img: {
          select: {
            img: true,
          },
        },
      },
      orderBy: {
        page_view: sort,
      },
    };

    const res = await this.paginationService.paginate(
      'scenic',
      query,
      pageNum,
      pageSize,
    );
    return res;
  }

  async getScenicDetail(id: number) {
    const res = await this.prisma.scenic.findUnique({
      where: {
        id,
      },
      include: {
        scenic_img: {
          select: {
            img: true,
          },
        },
      },
    });

    if (!res) {
      throw new HttpException('该景区不存在', HttpStatus.BAD_REQUEST);
    }
    return res;
  }

  async createScenic(data: any) {
    const {
      spot,
      region,
      addr,
      desc,
      detail,
      lng,
      lat,
      imgs,
      type,
      url,
      tel,
      open_time,
      visit_time,
    } = data;

    const spotData = await this.prisma.scenic.findUnique({
      where: { spot },
    });

    if (spotData)
      throw new HttpException('该景区已存在', HttpStatus.BAD_REQUEST);

    const imgsObj = imgs.map((img) => {
      return {
        img,
      };
    });

    const res = await this.prisma.scenic.create({
      data: {
        spot,
        region,
        addr,
        desc,
        detail,
        lng: +lng,
        lat: +lat,
        type,
        url,
        tel,
        open_time,
        visit_time,
        scenic_img: {
          create: [...imgsObj],
        },
      },
    });
    return res.id;
  }

  async updateScenic(data: any) {
    const {
      id,
      spot,
      region,
      addr,
      desc,
      detail,
      lng,
      lat,
      type,
      url,
      tel,
      open_time,
      visit_time,
      imgs,
    } = data;

    await this.getScenicDetail(id);

    const imgsObj = imgs.map((img) => {
      return {
        img,
      };
    });

    const deleteFn = this.prisma.scenic_img.deleteMany({
      where: {
        scenicId: id,
      },
    });

    const updateFn = this.prisma.scenic.update({
      where: { id },
      data: {
        spot,
        region,
        addr,
        desc,
        detail,
        lng: +lng,
        lat: +lat,
        type,
        url,
        tel,
        open_time,
        visit_time,
        scenic_img: {
          create: [...imgsObj],
        },
      },
    });

    return await this.prisma.$transaction([deleteFn, updateFn]);
  }

  async deleteScenic(id: number) {
    const spotData = await this.getScenicDetail(id);

    const deletePromises = [
      this.prisma.scenic_img.deleteMany({ where: { scenicId: +id } }),
      this.prisma.user_scenic.deleteMany({ where: { scenicId: +id } }),
      this.prisma.scenic.delete({ where: { id } }),
    ];
    await this.prisma.$transaction(deletePromises);

    const imgs = spotData.scenic_img.map((i) => i.img);
    imgs.length && this.MinioClientService.deleteMinioFile(imgs);

    return true;
  }

  async getCollectInfo(userId: number, scenicId: number) {
    const collect = await this.prisma.user_scenic.findFirst({
      where: {
        userId,
        scenicId,
      },
    });
    return !!collect;
  }
}
